package system

import (
	"errors"
	"time"

	"github.com/asynkron/protoactor-go/actor"
)

// System-level messages

// SpawnChildCommand is a command to spawn a child actor
type SpawnChildCommand struct {
	// Name is the name of the child actor
	Name string
	// Props are the props for the child actor
	Props *actor.Props
}

// SpawnChildResponse is the response to a SpawnChildCommand
type SpawnChildResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
	// PID is the PID of the spawned actor
	PID *actor.PID
}

// StopChildCommand is a command to stop a child actor
type StopChildCommand struct {
	// Name is the name of the child actor
	Name string
}

// StopChildResponse is the response to a StopChildCommand
type StopChildResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
}

// GetChildrenCommand is a command to get all children
type GetChildrenCommand struct{}

// GetChildrenResponse is the response to a GetChildrenCommand
type GetChildrenResponse struct {
	// Children is a map of child names to PIDs
	Children map[string]*actor.PID
}

// RestartCommand is a command to restart an actor
type RestartCommand struct{}

// SystemCommand is a general system command
type SystemCommand struct {
	// Command is the command to execute
	Command string
	// Params are the command parameters
	Params map[string]interface{}
}

// Error messages

// ErrorMessage is a message for reporting errors
type ErrorMessage struct {
	// ActorID is the ID of the actor reporting the error
	ActorID string
	// Error is the error being reported
	Error error
	// Severity is the error severity
	Severity string
	// Timestamp is when the error occurred
	Timestamp time.Time
	// Context contains additional error context
	Context map[string]interface{}
}

// Error types

// CriticalError represents a critical error that should stop the actor
type CriticalError struct {
	// Message is the error message
	Message string
	// Cause is the underlying error
	Cause error
}

// Error returns the error message
func (e *CriticalError) Error() string {
	if e.Cause != nil {
		return e.Message + ": " + e.Cause.Error()
	}
	return e.Message
}

// Unwrap returns the underlying error
func (e *CriticalError) Unwrap() error {
	return e.Cause
}

// TemporaryError represents a temporary error that should restart the actor
type TemporaryError struct {
	// Message is the error message
	Message string
	// Cause is the underlying error
	Cause error
	// RetryCount is the number of retries
	RetryCount int
}

// Error returns the error message
func (e *TemporaryError) Error() string {
	if e.Cause != nil {
		return e.Message + " (retry " + string(e.RetryCount) + "): " + e.Cause.Error()
	}
	return e.Message + " (retry " + string(e.RetryCount) + ")"
}

// Unwrap returns the underlying error
func (e *TemporaryError) Unwrap() error {
	return e.Cause
}

// NewCriticalError creates a new critical error
func NewCriticalError(message string, cause error) *CriticalError {
	return &CriticalError{
		Message: message,
		Cause:   cause,
	}
}

// NewTemporaryError creates a new temporary error
func NewTemporaryError(message string, cause error, retryCount int) *TemporaryError {
	return &TemporaryError{
		Message:    message,
		Cause:      cause,
		RetryCount: retryCount,
	}
}

// Workflow-level messages

// DeployWorkflowCommand is a command to deploy a workflow
type DeployWorkflowCommand struct {
	// WorkflowID is the ID of the workflow
	WorkflowID string
	// Definition is the workflow definition
	Definition interface{}
}

// DeployWorkflowResponse is the response to a DeployWorkflowCommand
type DeployWorkflowResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
	// WorkflowPID is the PID of the workflow actor
	WorkflowPID *actor.PID
}

// StartWorkflowCommand is a command to start a workflow
type StartWorkflowCommand struct {
	// WorkflowID is the ID of the workflow
	WorkflowID string
	// Parameters are the workflow parameters
	Parameters map[string]interface{}
}

// StartWorkflowResponse is the response to a StartWorkflowCommand
type StartWorkflowResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
	// RunID is the ID of the workflow run
	RunID string
}

// StopWorkflowCommand is a command to stop a workflow
type StopWorkflowCommand struct {
	// RunID is the ID of the workflow run
	RunID string
}

// StopWorkflowResponse is the response to a StopWorkflowCommand
type StopWorkflowResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
}

// GetWorkflowStatusCommand is a command to get workflow status
type GetWorkflowStatusCommand struct {
	// RunID is the ID of the workflow run
	RunID string
}

// GetWorkflowStatusResponse is the response to a GetWorkflowStatusCommand
type GetWorkflowStatusResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error message if the operation failed
	Error string
	// Status is the workflow status
	Status string
	// Progress is the workflow progress (0-100)
	Progress int
	// StartTime is when the workflow started
	StartTime time.Time
	// EndTime is when the workflow ended
	EndTime time.Time
	// NodeStatuses are the statuses of the workflow nodes
	NodeStatuses map[string]string
}

// Data messages

// DataMessage is a message containing data
type DataMessage struct {
	// MessageID is the unique ID of the message
	MessageID string
	// Data is the message data
	Data []byte
	// Metadata contains additional message metadata
	Metadata map[string]string
	// Timestamp is when the message was created
	Timestamp time.Time
	// SourceID is the ID of the source actor
	SourceID string
	// DestinationID is the ID of the destination actor
	DestinationID string
}

// State messages

// SaveStateCommand is a command to save state
type SaveStateCommand struct {
	// Key is the state key
	Key string
	// State is the state to save
	State interface{}
}

// SaveStateResponse is the response to a SaveStateCommand
type SaveStateResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error if the operation failed
	Error error
}

// LoadStateCommand is a command to load state
type LoadStateCommand struct {
	// Key is the state key
	Key string
}

// LoadStateResponse is the response to a LoadStateCommand
type LoadStateResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error if the operation failed
	Error error
	// State is the loaded state
	State interface{}
}

// CreateCheckpointCommand is a command to create a checkpoint
type CreateCheckpointCommand struct {
	// ID is the checkpoint ID
	ID string
}

// CreateCheckpointResponse is the response to a CreateCheckpointCommand
type CreateCheckpointResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error if the operation failed
	Error error
}

// RestoreFromCheckpointCommand is a command to restore from a checkpoint
type RestoreFromCheckpointCommand struct {
	// ID is the checkpoint ID
	ID string
}

// RestoreFromCheckpointResponse is the response to a RestoreFromCheckpointCommand
type RestoreFromCheckpointResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error if the operation failed
	Error error
}

// SubscribeToStateChangesCommand is a command to subscribe to state changes
type SubscribeToStateChangesCommand struct {
	// Key is the state key to subscribe to
	Key string
}

// SubscribeToStateChangesResponse is the response to a SubscribeToStateChangesCommand
type SubscribeToStateChangesResponse struct {
	// Success indicates if the operation was successful
	Success bool
	// Error is the error if the operation failed
	Error error
}

// StateChangedEvent is an event for state changes
type StateChangedEvent struct {
	// Key is the state key
	Key string
	// NewState is the new state
	NewState interface{}
	// OldState is the old state
	OldState interface{}
	// Timestamp is when the state changed
	Timestamp time.Time
}

// Common errors

var (
	// ErrNotFound is returned when a resource is not found
	ErrNotFound = errors.New("resource not found")
	// ErrAlreadyExists is returned when a resource already exists
	ErrAlreadyExists = errors.New("resource already exists")
	// ErrInvalidState is returned when an operation is invalid in the current state
	ErrInvalidState = errors.New("invalid state for operation")
	// ErrTimeout is returned when an operation times out
	ErrTimeout = errors.New("operation timed out")
	// ErrCancelled is returned when an operation is cancelled
	ErrCancelled = errors.New("operation cancelled")
)
